import {
  call, put, all, takeLatest, select
} from 'redux-saga/effects';
import api from '@API'
import {
  GET_DECISION_FLOWS,
  START_JOUNEY,
  MAKE_CHOICE,
  MOVE_TO_STEP,
  GET_SURVEY_TEMPLATES,
  START_SURVEY,
  MOVE_TO_SURVEY_STEP,
  SUBMIT_SURVEY,
  GET_DECISION_RESULT,
  GET_LAST_DECISION,
  GET_FLOWS_NUMBER,
  GET_DECISION_DETAIL,
  GET_RESULT_DOCTORS,
  GET_RESULT_FEEDITEMS,
  GET_TEMPLATES_BY_TAG_IDS, GET_RESULT_GOODS,
} from '@ACTIONS/decision'
import { UPDATE_START_SURVEY } from '@ACTIONS/servicePack'
import { DECISION_TYPE, FLOW_NODE_TYPE } from '@CONSTANTS/decision'
import Navigate from '@NAVIGATION/navigateManager'
import { getTagIds } from '@UTILS/common'
import { UPDATE_PAIN_MANAGEMENT } from '@ACTIONS/managementPlan'
import {
  getCurrentSurvey, getSurveyChoices, getSurveyTemplate, getServicePackDetail
} from './dataSelect'

const getDecisionFlows = function* getDecisionFlows(action) {
  try {
    const { isInitial } = action
    const { Flows } = yield call(api.getDecisionFlows, { skip: 0 })
    const list = Flows.map(flow => ({ ...flow, DecisionType: DECISION_TYPE.Decision })) || []
    yield put({ type: GET_DECISION_FLOWS.SUCCESS, list, isInitial })
  } catch (error) {
    yield put({ type: GET_DECISION_FLOWS.FAILURE, error })
  }
}

const getSurveyById = function* getSurveyById(action) {
  try {
    const { id, isSurvey } = action
    const data = isSurvey ? yield call(api.getSurveyById, { sId: id }) : yield call(api.getJourneyResultById, { jId: id })
    if (!isSurvey) {
      const { Tags, Instruction, DisplayText } = data.FlowNode || {}
      Object.assign(data, { Instruction, Tags, journeyTags: data.JourneyTags, DisplayText })
    }

    const { Tags, FeedItemTags, journeyTags } = data
    const dTagIds = getTagIds(Tags)
    const fTagIds = getTagIds(FeedItemTags)
    const jTags = getTagIds(journeyTags)
    yield put({ type: GET_DECISION_RESULT.SUCCESS, data })
    yield put({ type: GET_RESULT_DOCTORS.REQUEST, tIds: dTagIds })
    yield put({ type: GET_TEMPLATES_BY_TAG_IDS.REQUEST, tIds: isSurvey ? dTagIds : jTags })
    yield put({ type: GET_RESULT_FEEDITEMS.REQUEST, tIds: fTagIds })
    yield put({ type: GET_RESULT_GOODS.REQUEST, tIds: dTagIds })
  } catch (error) {
    yield put({ type: GET_DECISION_RESULT.FAILURE, decisionResultError: true, })
  }
}

const getTemplatesByTagIds = function* getTemplatesByTagIds(action) {
  try {
    const { tIds } = action
    if (!tIds?.length) return
    const { Templates } = yield call(api.getTemplatesByTagIds, { tIds: JSON.stringify(tIds) })
    yield put({ type: GET_TEMPLATES_BY_TAG_IDS.SUCCESS, templates: Templates })
  } catch (error) {
    yield put({ type: GET_TEMPLATES_BY_TAG_IDS.FAILURE, error })
  }
}

const getResultDoctors = function* getResultDoctors(action) {
  try {
    const { tIds } = action
    if (!tIds?.length) return
    const { Doctors } = yield call(api.getDoctorsByTagIds, { tIds: JSON.stringify(tIds) })
    yield put({ type: GET_RESULT_DOCTORS.SUCCESS, data: Doctors })
  } catch (error) {
    yield put({ type: GET_RESULT_DOCTORS.FAILURE, error })
  }
}

const getResultFeedItems = function* getResultFeedItems(action) {
  try {
    const { tIds } = action
    if (!tIds?.length) return
    const { FeedItems } = yield call(api.getNewsFeedByTagIds_V2, { tIds: JSON.stringify(tIds) })
    yield put({ type: GET_RESULT_FEEDITEMS.SUCCESS, data: FeedItems })
  } catch (error) {
    yield put({ type: GET_RESULT_FEEDITEMS.FAILURE, error })
  }
}

const getResultGoods = function* getResultGoods(action) {
  try {
    const { tIds } = action
    if (!tIds?.length) return
    const { GoodsList } = yield call(api.getGoodsByTagIds, { tIds: JSON.stringify(tIds) })
    yield put({ type: GET_RESULT_GOODS.SUCCESS, data: GoodsList })
  } catch (error) {
    yield put({ type: GET_RESULT_GOODS.FAILURE, error })
  }
}

const getSurveyTemplates = function* getSurveyTemplates(action) {
  try {
    const { isInitial } = action
    const { Templates } = yield call(api.getSurveyTemplates, { skip: 0, take: 100 })
    const list = Templates.map(tmp => ({ ...tmp, DecisionType: DECISION_TYPE.Survey })) || []
    yield put({ type: GET_SURVEY_TEMPLATES.SUCCESS, list, isInitial })
  } catch (error) {
    yield put({ type: GET_SURVEY_TEMPLATES.FAILURE, error })
  }
}

const startJouney = function* startJouney(action) {
  try {
    const { id, plan } = action
    const { planId, day } = plan || {}
    const params = { DecisionFlowId: id }
    if (planId) {
      params.Day = Number(day)
      params.PainManagementId = planId
    }
    const data = yield call(api.startJouney, params)
    yield put({ type: START_JOUNEY.SUCCESS, data })
  } catch (error) {
    yield put({ type: START_JOUNEY.FAILURE, error })
  }
}

const startSurvey = function* startSurvey(action) {
  try {
    const { id, journeyId, doctorId } = action
    const params = { TemplateId: id }
    journeyId && (params.BotJourneyId = journeyId)
    doctorId && (params.DoctorUserId = doctorId)
    const data = yield call(api.startSurvey, params)
    yield put({ type: START_SURVEY.SUCCESS, data })
  } catch (error) {
    yield put({ type: START_SURVEY.FAILURE, error })
  }
}

const makeChoice = function* makeChoice(action) {
  try {
    const { payload = {}, data: choice, plan } = action
    const params = { ...payload, ToNodeCode: choice?.NextNodeCode }
    const { planId, requestId } = plan || {}
    const data = yield call(api.makeChoice, params)
    yield put({ type: MAKE_CHOICE.SUCCESS, data })
    const { Type, JourneyId } = data
    if (Type === FLOW_NODE_TYPE.Leaf) {
      Navigate.redirectTo('decisionResultPage', { id: JourneyId, requestId })
      yield put({ type: GET_FLOWS_NUMBER.REQUEST })
      planId && (yield put({ type: UPDATE_PAIN_MANAGEMENT.REQUEST }))
    }
  } catch (error) {
    yield put({ type: MAKE_CHOICE.FAILURE, error })
  }
}

const moveToStep = function* moveToStep(action) {
  try {
    const { payload, data, plan } = action
    yield call(api.moveToStep, payload)
    yield put({ type: MAKE_CHOICE.REQUEST, payload, data, plan })
  } catch (error) {
    yield put({ type: MOVE_TO_STEP.FAILURE, error })
  }
}

const moveToSurveyStep = function* moveToSurveyStep(action) {
  try {
    const { payload = {} } = action
    const {
      code: questionCode, data, isFromServicepack, doctorId, backOne, appkey, isAssistant, requestId, prevScene
    } = payload
    const surveyTemplate = yield select(getSurveyTemplate)
    const { Questions } = surveyTemplate || {}
    const isSubmit = Questions.length === questionCode
    if (isSubmit) {
      yield put({
        type: SUBMIT_SURVEY.REQUEST,
        questionCode,
        data,
        isFromServicepack,
        doctorId,
        backOne,
        appkey,
        isAssistant,
        prevScene,
        requestId
      })
    } else {
      yield put({
        type: MOVE_TO_SURVEY_STEP.SUCCESS, questionCode, answerChoice: data
      })
    }
  } catch (error) {
    yield put({ type: MOVE_TO_SURVEY_STEP.FAILURE, error })
  }
}

const submitSurvey = function* submitSurvey(action) {
  try {
    const {
      questionCode, data, isFromServicepack, doctorId, backOne, appkey, isAssistant, requestId
    } = action
    const lastSurveyChoices = { Code: questionCode, AnswerChoice: data?.Label }
    const surveyChoices = yield select(getSurveyChoices)
    const currentSurvey = yield select(getCurrentSurvey)
    const servicePackDetail = yield select(getServicePackDetail)
    const { PackId } = servicePackDetail || {}
    const { p8Id, Template } = currentSurvey || {}
    const result = yield call(api.submitSurvey, { SurveyId: p8Id, QnA: surveyChoices.concat(lastSurveyChoices) })
    Navigate.redirectTo('decisionResultPage', {
      isSurvey: true, id: p8Id, doctorId, isFromServicepack, backOne, appkey, isAssistant, requestId
    })
    yield put({
      type: SUBMIT_SURVEY.SUCCESS, data: result, questionCode, lastSurveyChoices
    })
    yield put({ type: GET_LAST_DECISION.REQUEST, id: Template?.p8Id, isSurvey: true })
    yield put({ type: GET_FLOWS_NUMBER.REQUEST })

    if (isFromServicepack) {
      const { p8Id: SurveyId } = result
      if (PackId && SurveyId) {
        yield put({ type: UPDATE_START_SURVEY.REQUEST, payload: { PackId, SurveyId } })
      }
    }
  } catch (error) {
    yield put({ type: SUBMIT_SURVEY.FAILURE, error })
  }
}

const getLastSurvey = function* getLastSurvey(action) {
  try {
    const { id, isSurvey } = action
    const data = isSurvey ? yield call(api.getMyLastSurveyByTemplate, { tId: id }) : yield call(api.getMyLastJourneyByDecisionFlowId, { dfId: id })
    yield put({ type: GET_LAST_DECISION.SUCCESS, data })
  } catch (error) {
    yield put({ type: GET_LAST_DECISION.FAILURE, error })
  }
}

const getMyDistinctFlowsNumber = function* getMyDistinctFlowsNumber() {
  try {
    const data = yield all([
      call(api.getMyDistinctFlowsNumber),
      call(api.getMySurveyTemplatesNumber)
    ])
    yield put({ type: GET_FLOWS_NUMBER.SUCCESS, num: data.reduce((prev, curr) => prev + curr, 0) })
  } catch (error) {
    yield put({ type: GET_FLOWS_NUMBER.FAILURE, error })
  }
}

const getCurrentDecision = function* getCurrentDecision(action) {
  try {
    const { id, isSurvey } = action
    const data = isSurvey ? yield call(api.getSurveyTemplateById, { tId: id }) : yield call(api.getDecisionFlowById, { dfId: id })

    const { p8Id } = data
    yield put({ type: GET_LAST_DECISION.REQUEST, id: p8Id, isSurvey })

    yield put({ type: GET_DECISION_DETAIL.SUCCESS, data: { ...data, DecisionType: isSurvey ? DECISION_TYPE.Survey : DECISION_TYPE.Decision } })
  } catch (error) {
    yield put({ type: GET_DECISION_DETAIL.FAILURE, error })
  }
}

export default function* rootSaga() {
  yield all([
    takeLatest(GET_DECISION_FLOWS.REQUEST, getDecisionFlows),
    takeLatest(START_JOUNEY.REQUEST, startJouney),
    takeLatest(MAKE_CHOICE.REQUEST, makeChoice),
    takeLatest(MOVE_TO_STEP.REQUEST, moveToStep),
    takeLatest(GET_SURVEY_TEMPLATES.REQUEST, getSurveyTemplates),
    takeLatest(START_SURVEY.REQUEST, startSurvey),
    takeLatest(MOVE_TO_SURVEY_STEP.REQUEST, moveToSurveyStep),
    takeLatest(SUBMIT_SURVEY.REQUEST, submitSurvey),
    takeLatest(GET_DECISION_RESULT.REQUEST, getSurveyById),
    takeLatest(GET_LAST_DECISION.REQUEST, getLastSurvey),
    takeLatest(GET_FLOWS_NUMBER.REQUEST, getMyDistinctFlowsNumber),
    takeLatest(GET_DECISION_DETAIL.REQUEST, getCurrentDecision),
    takeLatest(GET_RESULT_DOCTORS.REQUEST, getResultDoctors),
    takeLatest(GET_RESULT_FEEDITEMS.REQUEST, getResultFeedItems),
    takeLatest(GET_RESULT_GOODS.REQUEST, getResultGoods),
    takeLatest(GET_TEMPLATES_BY_TAG_IDS.REQUEST, getTemplatesByTagIds),
  ])
}
